package edu.upenn.seas.peerreview.pr

import edu.upenn.seas.peerreview.{Id, Sink, Source}
import edu.upenn.seas.peerreview.pr.PRMessages._

class PRLayer (myId:Id, transport:Sink.T, f:Source.Factory) extends Source.T {
  val log: Log = new Log()
  var myUI : Id = null
  var okToReleaseLog : Boolean = false
   
  // the pipe mySM uses to send messages
  val sendPipe = new Sink.T {
    def apply(to: Id, msg: Message) = {
      msg match{
        case msg:OKToReleaseLog => 
          okToReleaseLog = true
        case PleaseAudit(i:Id) =>
          transport(i, PleaseSendYourLog())
        case _ => {
          val id : SeqNum = log.addSent(to, msg)
          transport(to, PR_SEND(msg, id))
        }
      }   
    }
  }
 
  val mySM = f(myId, sendPipe)
  
  // the write method for *this* which is the pipe Transport sends messages
  // to the SM through

  def apply(from:Id, msg:Message) = {
    msg match {
      case PleaseSendYourLog() =>
        if (okToReleaseLog) 
          transport(from, HereIsMyLog(log))
        else
          transport(from, HereIsMyLog(null))
          println ("Log requested before my UI said it was OK!")
      case HereIsMyLog(l:Log) =>
        mySM(myId, AuditResult(l.audit(f(from, _))))
      case PR_SEND(msg: Message, idSent: SeqNum) => {
        val idRec : SeqNum = log.addRecv(from, msg, idSent)
        mySM(from,msg)
      }
      case _ => 
        // -1 is wrong. need some way of adding things to log that
        // don't have a sent id sequence. or maybe it doesn't matter.
        // either way, get rid of arbitrary constant. -dan
        log.addRecv(from, msg, -1) 
        mySM(from, msg)
    }
  }
}
